package com.finance.cooperate.feature.service.impl;

import com.finance.cooperate.common.properties.CooperateProperties;
import com.finance.cooperate.common.utils.DateUtils;
import com.finance.cooperate.dao.entity.primary.App;
import com.finance.cooperate.dao.entity.secondary.FraudAppInstallDetail;
import com.finance.cooperate.dao.local.scope.CooperateRequestScope;
import com.finance.cooperate.dao.repository.primary.AppRepository;
import com.finance.cooperate.dao.repository.secondary.FraudAppInstallDetailRepository;
import com.finance.cooperate.dao.support.query.Filter;
import com.finance.cooperate.dao.support.query.QueryParams;
import com.finance.cooperate.feature.core.feature.applist.APPListFraud;
import com.finance.cooperate.feature.dto.AppInstallDetailDTO;
import com.finance.cooperate.feature.service.AppInstallDetailService;
import com.finance.cooperate.feature.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @ClassName AppInstallDetailServiceImpl
 * @Description TODO
 * @Author shenanxin
 * @Date 2023/8/23 16:16
 * @Modify ...
 */
@Slf4j
@Service
public class AppInstallDetailServiceImpl implements AppInstallDetailService {

    @Autowired
    private AppRepository appRepository;

    @Autowired
    private CooperateRequestScope requestScope;

    @Autowired
    private FraudAppInstallDetailRepository installDetailRepository;

    @Autowired
    private UserService userService;

    @Autowired
    private CooperateProperties cooperateProperties;

    @Override
    public AppInstallDetailDTO isFraudApp(String uid) {

        AppInstallDetailDTO dto = new AppInstallDetailDTO();

        // 如果不是线上环境，则不生效
        Boolean isDebug = cooperateProperties.getEnvironment().getIsDebug();
        if (isDebug) {
            return dto;
        }

        int maxSameApps = 0;

        String sameUid = null;

        String sameDeviceId = null;

        // 获取该用户安装的app列表
        Date lastSubmitTime = requestScope.getLastSubmitTime();

        String packageName = requestScope.getPackageName();

        List<App> appList = appRepository.getAppDropPre(uid, requestScope.getDeviceId(), lastSubmitTime);

        // 用户安装短信中位数为 55
        List<Long> installTimeList = new ArrayList<>();
        List<String> appPackageNameList = new ArrayList<>();
        for (App app : appList) {

            String appPackageName = app.getAppPackageName();

            if (APPListFraud.app.contains(appPackageName)) {

                // 需要纪录在案
                long installTime = DateUtils.getMillis10(DateUtils.toDate(app.getLastUpdateTime()));

                if(installTime <= 1262275200L) {
                    continue;
                }

                installTimeList.add(installTime);
                appPackageNameList.add(appPackageName);

            }
        }

        if (appPackageNameList.size() > 0) {
            List<FraudAppInstallDetail> detailList = installDetailRepository.findByCondition(
                    installTimeList,
                    packageName,
                    appPackageNameList,
                    DateUtils.getMillis(lastSubmitTime) - 15 * 24 * 60 * 60 * 1000,
                    DateUtils.getMillis(lastSubmitTime)
            );


            for (App app : appList) {

                String appPackageName = app.getAppPackageName();
                Long installTime = DateUtils.getMillis10(DateUtils.toDate(app.getLastUpdateTime()));

                // 遍历相同 用户
                for (FraudAppInstallDetail detail : detailList) {

                    String u = detail.getUid();
                    String apn_ = detail.getAppPackageName();
                    Long it_ = detail.getInstallTime();

                    if (!uid.equals(u) && appPackageName.equals(apn_) && installTime.equals(it_)) {

                        String deviceId = userService.getDeviceId(u);

                        // 把相同的用户app都取出来
                        List<App> historyApp = appRepository.getAppDropPre(u, deviceId, lastSubmitTime);

                        int sameApps = 0;

                        for (App p : appList) {

                            String apn = p.getAppPackageName();

                            if (APPListFraud.app.contains(apn)) {

                                // 需要纪录在案
                                long it = DateUtils.getMillis10(DateUtils.toDate(p.getLastUpdateTime()));

                                if (it <= 1262275200L) {
                                    continue;
                                }

                                for (App hp : historyApp) {

                                    String hapn = hp.getAppPackageName();

                                    if (hapn.equals(apn)) {

                                        long hit = DateUtils.getMillis10(DateUtils.toDate(hp.getLastUpdateTime()));

                                        if (it == hit) {
                                            sameApps++;
                                        }

                                    }
                                }
                            }
                        }

                        if (sameApps > maxSameApps) {
                            maxSameApps = sameApps;
                            sameUid = u;
                            sameDeviceId = deviceId;
                        }

                    }

                }

            }
        }

        // 保存app 安装详情
        this.saveAppInstallDetail(appList);

        dto.setSameAppCount(maxSameApps);
        dto.setSameUid(sameUid);
        dto.setCurrDeviceId(requestScope.getDeviceId());
        dto.setSameDeviceId(sameDeviceId);
        dto.setSameLastSubmitTime(DateUtils.toStr(lastSubmitTime));

        return dto;
    }

    public AppInstallDetailDTO isFraudApp_old(String uid) {

        AppInstallDetailDTO dto = new AppInstallDetailDTO();

        // 如果不是线上环境，则不生效
        Boolean isDebug = cooperateProperties.getEnvironment().getIsDebug();
        if (isDebug) {
            return dto;
        }

        int maxSameApps = 0;

        String sameUid = null;

        String sameDeviceId = null;

        // 获取该用户安装的app列表
        Date lastSubmitTime = requestScope.getLastSubmitTime();

        String packageName = requestScope.getPackageName();

        List<App> appList = appRepository.getAppDropPre(uid, requestScope.getDeviceId(), lastSubmitTime);

        // 用户安装短信中位数为 55
        for (App app : appList) {

            String appPackageName = app.getAppPackageName();

            if (APPListFraud.app.contains(appPackageName)) {

                // 需要纪录在案
                long installTime = DateUtils.getMillis10(DateUtils.toDate(app.getLastUpdateTime()));

                if(installTime <= 1262275200L) {
                    continue;
                }

                // 查询近15天时间戳相同的用户
                QueryParams<FraudAppInstallDetail> queryParams = new QueryParams<>();
                queryParams.and(
                        Filter.eq("installTime", installTime),
                        Filter.eq("packageName", packageName),
                        Filter.eq("appPackageName", appPackageName),
                        Filter.gt("created", DateUtils.getMillis(lastSubmitTime) - 15 * 24 * 60 * 60 * 1000),
                        // 因为离线可能要分析，所以卡下结束时间
                        Filter.le("created", DateUtils.getMillis(lastSubmitTime)),
                        Filter.ne("uid", uid)
                );


                List<FraudAppInstallDetail> detailList = installDetailRepository.findAll(queryParams);

                // 遍历相同 用户
                for (FraudAppInstallDetail detail : detailList) {
                    String u = detail.getUid();

                    String deviceId = userService.getDeviceId(u);

                    // 把相同的用户app都取出来
                    List<App> historyApp = appRepository.getAppDropPre(u, deviceId, lastSubmitTime);

                    int sameApps = 0;

                    for (App p : appList) {

                        String apn = p.getAppPackageName();

                        if (APPListFraud.app.contains(apn)) {

                            // 需要纪录在案
                            long it = DateUtils.getMillis10(DateUtils.toDate(p.getLastUpdateTime()));

                            if (it <= 1262275200L) {
                                continue;
                            }

                            for (App hp : historyApp) {

                                String hapn = hp.getAppPackageName();

                                if (hapn.equals(apn)) {

                                    long hit = DateUtils.getMillis10(DateUtils.toDate(hp.getLastUpdateTime()));

                                    if (it == hit) {
                                        sameApps++;
                                    }

                                }
                            }
                        }
                    }

                    if (sameApps > maxSameApps) {
                        maxSameApps = sameApps;
                        sameUid = u;
                        sameDeviceId = deviceId;
                    }
                }
            }
        }

        // 保存app 安装详情
        this.saveAppInstallDetail(appList);


        dto.setSameAppCount(maxSameApps);
        dto.setSameUid(sameUid);
        dto.setCurrDeviceId(requestScope.getDeviceId());
        dto.setSameDeviceId(sameDeviceId);
        dto.setSameLastSubmitTime(DateUtils.toStr(lastSubmitTime));


        return dto;
    }


    private void saveAppInstallDetail(List<App> appList) {

        String packageName = requestScope.getPackageName();

        Date lastSubmitTime = requestScope.getLastSubmitTime();

        List<FraudAppInstallDetail> detailList = new ArrayList<>();

        for (App app : appList) {

            String appPackageName = app.getAppPackageName();

            if (APPListFraud.app.contains(appPackageName)) {

                // 需要纪录在案
                long installTime = DateUtils.getMillis10(DateUtils.toDate(app.getLastUpdateTime()));

                // 需要去下空
                if(installTime > 1262275200L) {

                    FraudAppInstallDetail detail = new FraudAppInstallDetail();

                    detail.setInstallTime(installTime);
                    detail.setAppPackageName(appPackageName);
                    detail.setUid(app.getUserId());
                    detail.setPackageName(packageName);
                    // 这里存的是用户近件时间
                    detail.setCreated(DateUtils.getMillis(lastSubmitTime));

                    // 重复不保存
                    List<FraudAppInstallDetail> findAll = installDetailRepository.findAll(Example.of(detail));

                    if (findAll.size() <= 0) {
                        detailList.add(detail);
                    }

                }

            }

        }


        if (detailList.size() > 0) {
            installDetailRepository.saveAll(detailList);
        }

    }

}
